package site.luojie.platform.gateway.filter;

import org.apache.dubbo.config.annotation.Reference;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.util.AntPathMatcher;
import org.springframework.util.StringUtils;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import site.luojie.common.service.UserRemoteService;
import site.luojie.common.vo.ResultVo;
import site.luojie.platform.gateway.config.CustomAuthAnonConfig;

import java.nio.charset.StandardCharsets;
import java.util.List;

/**
 * @author jie.luo
 * @since 2020/9/18
 */
@Component
public class AuthGlobalFilter implements GlobalFilter, Ordered {

    @Autowired
    private CustomAuthAnonConfig customAuthAnonConfig;
    @Reference
    private UserRemoteService userRemoteService;
    private final AntPathMatcher antPathMatcher = new AntPathMatcher();

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {

        // 当前请求url
        String path = exchange.getRequest().getURI().getPath();
        final List<String> anonUrls = customAuthAnonConfig.getUrls();
        for (String anonUrl : anonUrls) {
            boolean match = antPathMatcher.match(anonUrl, path);
            // 不需要token校验
            if (match) {
                return chain.filter(exchange);
            }
        }

        String authorization = exchange.getRequest().getHeaders().getFirst("Authorization");

        String forbidden = "{\"code\":\"401\",\"message\":\"请先登录\"}";
        if (StringUtils.isEmpty(authorization)) {
            return response(exchange, forbidden);
        }

        ResultVo<Boolean> booleanResultVo = userRemoteService.checkToken(authorization);
        if (!"200".equals(booleanResultVo.getCode()) || !booleanResultVo.getData()) {
            return response(exchange, forbidden);
        }

        return chain.filter(exchange);
    }

    public Mono<Void> response(ServerWebExchange exchange, String responseContent) {
        ServerHttpResponse originalResponse = exchange.getResponse();
        originalResponse.setStatusCode(HttpStatus.OK);
        originalResponse.getHeaders().add("Content-Type", "application/json;charset=UTF-8");
        byte[] response = responseContent.getBytes(StandardCharsets.UTF_8);
        DataBuffer buffer = originalResponse.bufferFactory().wrap(response);
        return originalResponse.writeWith(Flux.just(buffer));
    }

    @Override
    public int getOrder() {
        return 300;
    }
}
